<?php

namespace tmcore\services\addons;

use think\Route;
use think\Console;
use think\facade\Config;
use think\facade\Event;
use think\facade\Lang;

/**
 * 插件注册服务
 */
class AddonService extends \think\Service
{
    protected string $addon_path;

    protected array $addon_config;

    protected array $addon_commands = [];

    protected array $addon_events = [];

    protected array $addon_lang_files = [];

    protected array $addon_common_files = [];

    protected array $addon_routes = [];

    public function register(): void
    {
        // 获取插件路径
        $this->addon_path = UtilService::getAddonsPath();
        // 获取插件配置
        $this->addon_config = Config::get('addons');
        // 检验是否加载
        if(empty($this->addon_config['autoload'])) {
            $this->app->bind('addons', AddonService::class);
            return;
        }
        // 自动载入插件
        $this->autoload();
        // 加载插件语言
        $this->loadLang();
        // 加载插件公共文件
        $this->loadCommon();
        // 加载插件事件
        $this->loadEvent();
        // 挂载插件路由
        $this->loadRoutes();
        // 加载插件配置
        $this->loadCommands();
        // 清理内存
        $this->clearCache();
        // 绑定插件容器
        $this->app->bind('addons', AddonService::class);
    }

    /**
     * 自动载入插件
     * @return void
     */
    private function autoload(): void
    {
        $addon_key_list = UtilService::getInstallAddons();

        $this->addon_lang_files[] = $this->app->getRootPath() . 'tmcore/services/addons/lang/zh-cn.php';

        if(!empty($this->addon_config['events']))$this->addon_events = $this->addon_config['events'];

        if(!empty($this->addon_config['routes']))$this->addon_routes = $this->addon_config['routes'];

        foreach ($addon_key_list as $addon_key) {

            // 插件目录
            $addon_dir = $this->addon_path . $addon_key . DIRECTORY_SEPARATOR;

            // 插件基类文件
            $addon_base_file = $addon_dir . 'Addon.php';
            // 插件信息文件
            $addon_info_file = $addon_dir . 'info.php';
            // 插件配置文件
            $addon_config_file = $addon_dir . 'config.php';
            // 基础文件检验
            if(!file_exists($addon_base_file)) continue;
            if(!file_exists($addon_info_file)) continue;

            // 插件事件文件
            $addon_event_file = $addon_dir . 'event.php';
            if(is_file($addon_event_file)) {
                $event_config = include $addon_event_file;
                foreach ($event_config as $key => $event_value) {
                    $this->addon_events[($addon_key . '_' . $key)] = $event_value;
                }
            }

            // 插件语言文件
            $addon_lang_file = $addon_dir . 'lang' . DIRECTORY_SEPARATOR . 'zh-cn.php';
            if(is_file($addon_lang_file)) {
                $this->addon_lang_files[] = $addon_lang_file;
            }

            // 插件公共文件
            $addon_common_file = $addon_dir . 'common.php';
            if(is_file($addon_common_file)) {
                $this->addon_common_files[] = $addon_common_file;
            }

            // 插件路由文件
            $addon_routes = [];
            $addon_route_dir = $addon_dir . 'route' . DIRECTORY_SEPARATOR;
            $route_file_fixed = !empty($this->addon_config['route_file_fixed']);
            if(is_file($addon_config_file)) {
                $temp_arr = (array)include $addon_config_file;
                if(isset($temp_arr['route_file_fixed'])) $route_file_fixed = $temp_arr['route_file_fixed'];
                unset($temp_arr);
            }

            if($route_file_fixed) {
                // 固定路由文件
                if(is_file($addon_route_dir . 'route.php')) {
                    $addon_routes[] = $addon_key . DIRECTORY_SEPARATOR . 'route' . DIRECTORY_SEPARATOR . 'route.php';
                }
                foreach ($this->addon_config['app_map'] as $app_value) {
                    $addon_route_file = $addon_route_dir . $app_value .DIRECTORY_SEPARATOR . 'route.php';
                    if(is_file($addon_route_file)) {
                        $this->addon_routes[] = $addon_key . DIRECTORY_SEPARATOR . 'route' . DIRECTORY_SEPARATOR . $app_value .DIRECTORY_SEPARATOR . 'route.php';
                    }
                }
            } else {
                // 遍历路由文件夹
                $results = UtilService::getAddonsDirFiles($addon_key . DIRECTORY_SEPARATOR . 'route' . DIRECTORY_SEPARATOR);
                $this->addon_routes = array_merge($this->addon_routes, $results);
            }

            // 插件命令文件
            $addon_command_file = $addon_dir . 'command.php';
            if(is_file($addon_command_file)) {
                $command_config = include $addon_command_file;
                if($command_config) {
                    $commands = [];
                    foreach ($command_config as $key => $command) {
                        $commands[$addon_key . ':' . $key] = $command;
                    }
                    $this->addon_commands = array_merge($this->addon_commands, $commands);
                }
            }
        }
    }

    public function boot()
    {
        // 检验是否强制路由
        if (!empty($this->addon_config['url_route_must'])) {
            return;
        }

        // 注册路由
        $this->registerRoutes(function (Route $route) {
            // 路由脚本
            $execute = '\\tmcore\\services\\addons\\RouteService::execute';

            // 注册控制器路由
            $route->rule("addons/:addon/[:controller]/[:action]", $execute)
                ->middleware($this->addon_config['middleware']);
        });
    }

    /**
     * 加载语言
     * @return void
     */
    private function loadLang(): void
    {
        Lang::load($this->addon_lang_files);
    }

    /**
     * 加载公共文件
     * @return void
     */
    private function loadCommon(): void
    {
        $addonCommons = $this->addon_common_files;
        // 循环加载公共文件
        foreach ($addonCommons as $key => $value) {
            include_once $value;
        }
    }

    /**
     * 加载插件事件
     * @return void
     */
    private function loadEvent(): void
    {
        $addonEvents = $this->addon_events;
        // 循环注册事件
        foreach ($addonEvents as $key => $values) {
            if(is_array($values)) {
                foreach ($values as $value) {
                    if (class_exists($value)) {
                        Event::listen($key, $value);
                    }
                }
            } else {
                if (class_exists($values)) {
                    Event::listen($key, $values);
                }
            }
        }
    }

    /**
     * 加载插件路由
     * @return void
     */
    private function loadRoutes(): void
    {
        $addonRoutes = $this->addon_routes;

        // 循环加载路由文件
        $this->registerRoutes(function () use ($addonRoutes) {
            foreach ($addonRoutes as $key => $value) {
                include $this->addon_path . $value;
            }
        });
    }

    /**
     * 加载插件命令
     * @return void
     */
    private function loadCommands(): void
    {
        $addonCommands = $this->addon_commands;
        // 加载插件命令
        if ($addonCommands) {
            Console::starting(function (Console $console) use($addonCommands) {
                $console->addCommands($addonCommands);
            });
        }
    }

    /**
     * 清理内存
     * @return void
     */
    private function clearCache(): void
    {
        $this->addon_events = [];
        $this->addon_commands = [];
        $this->addon_lang_files = [];
        $this->addon_common_files = [];
        $this->addon_routes = [];
    }

}